<?php
/**
 * 发送http请求
 *
 *
 */

class HttpWrapper {

	//连接超时
	const CONNECT_TIMEOUT =		5;
	//读取超时
	const READ_TIMEOUT =		5;

	const POST =				'POST';
	const GET =					'GET';
	//开启socket调试
	const DEBUG_SOCKET =		false;

	/**
	 * 创建套接字方式的http的请求
	 */
	static public function httpRequestSocket($url, $type = "GET", $post_data = NULL, $fsock_timeout = self::CONNECT_TIMEOUT, $timeout=self::READ_TIMEOUT){
		$http_info = array();
		$url2 = parse_url($url);
		$url2["path"] = ($url2["path"] == "" ? "/" : $url2["path"]);
		$url2["port"] = !$url2["port"] ? 80 : $url2["port"];
		$host_ip = @gethostbyname($url2["host"]);
		$request =  $url2["path"] . ( isset($url2["query"]) && isset($url2["query"]) != "" ? "?" . $url2["query"] : "") . ( isset($url2["fragment"]) && $url2["fragment"] != "" ? "#" . $url2["fragment"] : "");
		$fsock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
		if(!$fsock){
			return false;
		}
		socket_set_nonblock($fsock);
		@socket_connect($fsock, $host_ip, $url2["port"]);

		$ret = socket_select($fd_read = array($fsock), $fd_write = array($fsock), $except = NULL, $fsock_timeout, 0);
		if($ret === false){
			return false;
		}elseif ($ret != 1){
			return false;
		}
		if($type == "GET"){//GET method
			$in = "GET " . $request . " HTTP/1.0\r\n";
			$in .= "Accept: */*\r\n";
			$in .= "User-Agent: 139.com API PHP5 Client\r\n";
			$in .= "Host: " . $url2["host"] . "\r\n";
			$in .= "Connection: Keep-Alive\r\n\r\n";
		}else if($type == "POST"){//POST method
			//build post data
			$needChar = false;
			$post_data2 = null;
			foreach($post_data as $key => $val)	{
				$post_data2 .= ($needChar ? "&" : "") . urlencode($key) . "=" . urlencode($val);
				$needChar = true;
			}
			$in  = "POST " . $request . " HTTP/1.0\r\n";
			$in .= "Accept: */*\r\n";
			$in .= "Host: " . $url2["host"] . "\r\n";
			$in .= "User-Agent: http-Agent\r\n";
			$in .= "Content-type: application/x-www-form-urlencoded\r\n";
			$in .= "Content-Length: " . strlen($post_data2) . "\r\n";
			$in .= "Connection: Close\r\n\r\n";
			$in .= $post_data2 . "\r\n\r\n";
			unset($post_data2);
		}else{
			return false;
		}
		if(!@socket_write($fsock, $in, strlen($in))){
			socket_close($fsock);
			return false;
		}
		unset($in);
		socket_set_block($fsock);
		@socket_set_option($fsock, SOL_SOCKET, SO_RCVTIMEO, array("sec" => $timeout, "usec" => 0));
		//process response
		$out = "";
		while($buff = socket_read($fsock, 2048)){
			$out .= $buff;
		}
		//finish socket
		@socket_close($fsock);
		if(!$out){
			return '';
		}

		$pos = strpos($out, "\r\n\r\n");
		$head = substr($out, 0, $pos);		//http head
		$status = substr($head, 0, strpos($head, "\r\n"));		//http status line
		$body = substr($out, $pos + 4);		//page body
		if( preg_match("/^HTTP\/\d\.\d\s(\d{3,4})\s/", $status, $matches) ){
			if(intval($matches[1]) / 100 == 2){
				return $body;
			}else{
				return NULL;
			}
		}else{
			return false;
		}
	}

	/**
	 * 使用curl封装的http请求
	 * @param string $url
	 * @param string $type
	 * @param string $post_data
	 * @param int $fsock_timeout
	 * @param int $timeout
	 * @param array $custom_headers 自定义header头
	 */
	static function httpRequestCurl($url, $type=self::GET, $post_data=NULL, $fsock_timeout=self::CONNECT_TIMEOUT, $timeout=self::READ_TIMEOUT, $custom_headers=array()) {
		static $curl = null;
		if (!$curl) {
			$curl = curl_init();
			curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $fsock_timeout);
			curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
			curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
			curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($curl, CURLOPT_USERAGENT, '139.com Microlog API');
		}

		if (!empty($custom_headers)) {
			curl_setopt($curl, CURLOPT_HTTPHEADER, $custom_headers);
		}

		curl_setopt($curl, CURLOPT_URL, $url);
		if($type == self::POST){
			curl_setopt($curl, CURLOPT_POST, true);
			curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
		}

		/*
		if(curl_errno($curl)){
		    error_log('curl:'.curl_errno($curl).', '.curl_error($curl).", $url\n", 3, "/tmp/xudawei.log");
		}
		*/

		$result = curl_exec($curl);
		return $result;
	}

	/**
	 * 发送http请求
	 * @param string $url
	 * @param string $type
	 * @param string $post_data
	 * @param int $fsock_timeout
	 * @param int $timeout
	 * @param array $custom_headers 自定义header头
	 */
	static public function httpRequest($url, $type=self::GET, $post_data=NULL, $fsock_timeout=self::CONNECT_TIMEOUT, $timeout=self::READ_TIMEOUT, $custom_headers=array()){
		if( self::DEBUG_SOCKET ){
			return self::httpRequestSocket($url, $type, $post_data, $fsock_timeout, $timeout);
		}else{
			return self::httpRequestCurl($url, $type, $post_data, $fsock_timeout, $timeout, $custom_headers);
		}
	}
}
